package com.kang.commons.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.kang.bean.AccessToken;
import com.kang.commons.Result;
import com.kang.commons.util.EncryptUtil;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @program: fawukang
 * @description: 请求拦截器 @Aspect // 表示这是个切面类
 * @author: K.faWu
 * @create: 2021-09-17 16:36
 **/
@Aspect
@Component
@Slf4j
public class RequestInterceptor {
    /**
     * 切入点： * com.kang.controller.*(..)
     * 第一个*是指任何权限，任何返回值都可以执行
     * 第二个* 指任何方法
     * (..) .. 表示任意参数的方法
     * //@Before("execution(* com.kang.controller.*(..))") 在方法之前执行 前置执行
     * // @After("execution(* com.kang.controller.*(..))") 在方法之后执行 后置执行
     */
    @Around("execution(* com.kang.controller..*.*(..))") // 环绕执行
    public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable {

        Signature signature = pjp.getSignature();
        Object target = pjp.getTarget();
        //当前执行的方法所属的类、包
        String className = target.getClass().getName();
        Object result;
        if (beforeController()) {
            try {
                result = pjp.proceed();
            } finally {
                log.info("方法" + className + "." + signature.getName() + " 执行完毕");
            }
        }else {
            return Result.error("请重新登录！");
        }
        return result;
    }

    /**
     * 记录接口执行日志
     */
    public boolean beforeController(){
        // 请求参数
        ServletRequestAttributes sre = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sre.getRequest();
        HttpServletResponse response = sre.getResponse();
        String requestUrl;
        requestUrl = request.getRequestURL().toString();
        // 表示不需要token的请求
        if (requestUrl.contains("photo") || requestUrl.contains("websocket") || requestUrl.contains("public") || requestUrl.contains("upload") || requestUrl.contains("msg")){
            return true;
        }
        String token = request.getHeader("token");
        if (token== null ||"null".equals(token)){
            return false;
        }

        String tokenJson = EncryptUtil.decrypt(token);
        AccessToken accessToken = JSONObject.parseObject(tokenJson, AccessToken.class);
        //判断是否过期
        if(System.currentTimeMillis() - accessToken.getExpire() > 0){
            log.warn("{}认证信息过期，请重新登录！",accessToken.getUserId());
            return false;
        }
        // 如果有效期在10分钟之内，重新生成一个token
        if(accessToken.getExpire() - System.currentTimeMillis() <= (10* 60* 1000)){
            log.info("创建新的token");
            accessToken = new AccessToken(accessToken.getUserId());
            String newToken = EncryptUtil.encrypt(JSONObject.toJSONString(accessToken));
            response.setHeader("token", newToken);
        }
        return true;
    }
}
